package lifeOfAFish.scenegraph;

public class sgVec3 {

	float[] v = new float[4];
	
	/**
	 * default constructor
	 */
	public sgVec3() {
	}
	/**
	 * create with given coords
	 * @param x coordinate x
	 * @param y coordinate y
	 * @param z coordinate z
	 */
	
	public sgVec3(float x, float y, float z){
		v[0] = x; v[1] = y; v[2] = z;
		v[3] = 1.0f;
	}
	
	/**
	 * create from an array
	 * @param v array containing vector 
	 */
	public sgVec3(float[] v){
		for(int i = 0; i < v.length; i++){
			this.v[i] = v[i];
		}
		if (v.length < 4) this.v[3] = 1.0f;
	}
	 
	/**
	 * Copy constructor
	 * @param v2 another sgVec3h to intialise from 
	 */
	// create as copy of another sgVec3
	public sgVec3(sgVec3 v2){
		this.copy(v2);	
	}
	
	/**
	 * clone this vector
	 */
	public sgVec3 clone(){
		return new sgVec3(this);
	}
	
	
	///////////////////////////////////
	// operations
	///////////////////////////////////
	
	/**
	 * Multiply by a Matrix
	 */
	public static sgVec3 multiply(float[] M, sgVec3 V){
		
		// build a new vector 
		float[] f = new float[4];
		for (int i=0;i<4;i++) {
			f[i]=0.0f;   
			for(int j=0;j<4;j++) 
				f[i]+=M[j*4 + i]*V.v[j];
		}
		
		// copy new array
		sgVec3 ret = new sgVec3(f);
		return ret;
	}
	
	/**
	 * dot product
	 * @param V1 Vector 1
	 * @param V2 Vector 2
	 * @return dot product
	 */
	public static float dot(sgVec3 V1, sgVec3 V2)
	{
		float val = 0;
		for (int i = 0 ; i < 3; i++)
			val += V1.v[i]*V2.v[i];
		return val;
	}
	
	/**
	 * cross product 
	 * @param V1 Vector1
	 * @param V2 Vector2
	 * @return resulting cross product
	 */
	public static sgVec3 cross(sgVec3 V1, sgVec3 V2){
		sgVec3 tmp = new sgVec3();
    	tmp.v[0]=V1.v[1]*V2.v[2] - V1.v[2]*V2.v[1];  	//y1*z2 - z1*y2
    	tmp.v[1]=V1.v[2]*V2.v[0] - V1.v[0]*V2.v[2];		// z1*x2 - x1*z2
    	tmp.v[2]=V1.v[0]*V2.v[1] - V1.v[1]*V2.v[0];		// x1*y2 - y1*x2
    	tmp.v[3]=1.0f;
    	return tmp;
	}
	
	/**
	 * Add two vectors
	 * @param V1 Vector1
	 * @param V2 Vector2
	 * @return Sum of V1 and V2
	 */
	public static sgVec3 add(sgVec3 V1, sgVec3 V2){
		sgVec3 tmp = new sgVec3();
    	tmp.v[0]=V1.v[0]+V2.v[0];
    	tmp.v[1]=V1.v[1]+V2.v[1];
    	tmp.v[2]=V1.v[2]+V2.v[2];
    	return tmp;
	}
	
	/**
	 * Subtract two vectors
	 * @param V1 Vector1
	 * @param V2 Vector2
	 * @return Difference of V1 and V2
	 */
	public static sgVec3 subtract(sgVec3 V1, sgVec3 V2){
		sgVec3 tmp = new sgVec3();
    	tmp.v[0]=V1.v[0]-V2.v[0];
    	tmp.v[1]=V1.v[1]-V2.v[1];
    	tmp.v[2]=V1.v[2]-V2.v[2];
    	tmp.v[3]=1.0f;
    	return tmp;
	}
	
	/**
	 * Get the length of this vector
	 * @return length of vector
	 */
	public float length(){
		// get length
		float abs = (float)Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
		return abs;
	}
	
	/**
	 * normalize the vector
	 * @return the normalized vector
	 */
	public sgVec3 norm(){
		
		// get length
		float abs = (float)Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
		
		// if 0, just return 0 vector
		if (abs == 0) 
			return new sgVec3(0.0f, 0.0f, 0.0f);
		
		// take norm
		v[0] /= abs;
		v[1] /= abs;
		v[2] /= abs;
		return this;
	}
	
	// getters
	public float getX() {return this.v[0]; }
	public float getY() {return this.v[1]; }
	public float getZ() {return this.v[2]; }
	public float[] getV() {return this.v; }
	
	// setters
	public void setX(float x) { v[0] = x; }
	public void setY(float y) { v[1] = y; }
	public void setZ(float z) { v[2] = z; }
	
	
	// copy values from another Vector
	private void copy(sgVec3 v2){
		this.v[0] = v2.v[0];
		this.v[1] = v2.v[1];
		this.v[2] = v2.v[2];
		this.v[3] = v2.v[3];
	}
	
	// Private functions //////////////////////////////
	
	// copies two equally long arrays of floats
	private void arrayCopy(float[] a, float[] b){
	
		if (a.length != b.length) return;
		
		for (int i=0; i<a.length; i++)
			a[i] = b[i];
	}
		
	
	public String toString() {
		
		return "(" + v[0] + "," + v[1] + "," + v[2] + ")";
	}
		
	
	
}